package com.kexio.security.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import java.time.LocalDateTime;

/**
 * 登录响应DTO
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Data
@Schema(description = "登录响应DTO")
public class LoginResponse {

    /**
     * 访问令牌
     */
    @Schema(description = "访问令牌", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
    private String accessToken;

    /**
     * 刷新令牌
     */
    @Schema(description = "刷新令牌", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
    private String refreshToken;

    /**
     * 令牌类型
     */
    @Schema(description = "令牌类型", example = "Bearer")
    private String tokenType = "Bearer";

    /**
     * 过期时间（秒）
     */
    @Schema(description = "过期时间（秒）", example = "7200")
    private Long expiresIn;

    /**
     * 会话ID
     */
    @Schema(description = "会话ID", example = "sess_1234567890")
    private String sessionId;

    /**
     * 用户信息
     */
    @Schema(description = "用户信息")
    private UserDTO userInfo;

    /**
     * 权限列表
     */
    @Schema(description = "权限列表", example = "[\"user:create\", \"user:update\"]")
    private java.util.Set<String> permissions;

    /**
     * 角色列表
     */
    @Schema(description = "角色列表", example = "[\"ADMIN\", \"USER\"]")
    private java.util.Set<String> roles;

    /**
     * 菜单权限
     */
    @Schema(description = "菜单权限")
    private java.util.List<MenuPermissionDTO> menus;

    /**
     * 登录时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "登录时间", example = "2024-01-01 12:00:00")
    private LocalDateTime loginTime;

    /**
     * 过期时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "过期时间", example = "2024-01-01 20:00:00")
    private LocalDateTime expireTime;

    /**
     * 设备类型
     */
    @Schema(description = "设备类型", example = "web")
    private String deviceType;

    /**
     * 登录IP
     */
    @Schema(description = "登录IP", example = "192.168.1.100")
    private String loginIp;

    /**
     * 是否首次登录
     */
    @Schema(description = "是否首次登录", example = "false")
    private Boolean firstLogin = false;

    /**
     * 是否需要修改密码
     */
    @Schema(description = "是否需要修改密码", example = "false")
    private Boolean needChangePassword = false;

    // ==================== 静态工厂方法 ====================

    /**
     * 创建成功的登录响应
     * @param accessToken 访问令牌
     * @param refreshToken 刷新令牌
     * @param expiresIn 过期时间（秒）
     * @param userInfo 用户信息
     * @return 登录响应
     */
    public static LoginResponse success(String accessToken, String refreshToken, 
                                       Long expiresIn, UserDTO userInfo) {
        LoginResponse response = new LoginResponse();
        response.setAccessToken(accessToken);
        response.setRefreshToken(refreshToken);
        response.setExpiresIn(expiresIn);
        response.setUserInfo(userInfo);
        response.setLoginTime(LocalDateTime.now());
        
        if (expiresIn != null) {
            response.setExpireTime(LocalDateTime.now().plusSeconds(expiresIn));
        }
        
        return response;
    }

    /**
     * 创建需要修改密码的响应
     * @param userInfo 用户信息
     * @return 登录响应
     */
    public static LoginResponse needChangePassword(UserDTO userInfo) {
        LoginResponse response = new LoginResponse();
        response.setUserInfo(userInfo);
        response.setNeedChangePassword(true);
        response.setLoginTime(LocalDateTime.now());
        return response;
    }

    /**
     * 创建首次登录的响应
     * @param accessToken 访问令牌
     * @param refreshToken 刷新令牌
     * @param expiresIn 过期时间（秒）
     * @param userInfo 用户信息
     * @return 登录响应
     */
    public static LoginResponse firstLogin(String accessToken, String refreshToken, 
                                         Long expiresIn, UserDTO userInfo) {
        LoginResponse response = success(accessToken, refreshToken, expiresIn, userInfo);
        response.setFirstLogin(true);
        return response;
    }

    // ==================== 便利方法 ====================

    /**
     * 检查是否登录成功
     * @return 是否成功
     */
    public boolean isSuccess() {
        return accessToken != null && !accessToken.trim().isEmpty();
    }

    /**
     * 检查令牌是否即将过期（30分钟内）
     * @return 是否即将过期
     */
    public boolean isAboutToExpire() {
        if (expireTime == null) {
            return false;
        }
        return LocalDateTime.now().plusMinutes(30).isAfter(expireTime);
    }

    /**
     * 检查令牌是否已过期
     * @return 是否已过期
     */
    public boolean isExpired() {
        if (expireTime == null) {
            return false;
        }
        return LocalDateTime.now().isAfter(expireTime);
    }

    /**
     * 获取剩余有效时间（分钟）
     * @return 剩余时间
     */
    public long getRemainingMinutes() {
        if (expireTime == null) {
            return Long.MAX_VALUE;
        }
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(expireTime)) {
            return 0;
        }
        return java.time.Duration.between(now, expireTime).toMinutes();
    }

    /**
     * 清除敏感信息（用于日志记录）
     */
    public void clearSensitiveInfo() {
        this.accessToken = "****";
        this.refreshToken = "****";
    }

    // ==================== 手写Setter方法 ====================
    
    public void setAccessToken(String accessToken) { this.accessToken = accessToken; }
    public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; }
    public void setTokenType(String tokenType) { this.tokenType = tokenType; }
    public void setExpiresIn(Long expiresIn) { this.expiresIn = expiresIn; }
    public void setSessionId(String sessionId) { this.sessionId = sessionId; }
    public void setUserInfo(UserDTO userInfo) { this.userInfo = userInfo; }
    public void setPermissions(java.util.Set<String> permissions) { this.permissions = permissions; }
    public void setRoles(java.util.Set<String> roles) { this.roles = roles; }
    public void setMenus(java.util.List<MenuPermissionDTO> menus) { this.menus = menus; }
    public void setLoginTime(LocalDateTime loginTime) { this.loginTime = loginTime; }
    public void setExpireTime(LocalDateTime expireTime) { this.expireTime = expireTime; }
    public void setDeviceType(String deviceType) { this.deviceType = deviceType; }
    public void setLoginIp(String loginIp) { this.loginIp = loginIp; }
    public void setFirstLogin(Boolean firstLogin) { this.firstLogin = firstLogin; }
    public void setNeedChangePassword(Boolean needChangePassword) { this.needChangePassword = needChangePassword; }

    // ==================== 内部类 ====================

    /**
     * 菜单权限DTO
     */
    @Data
    @Schema(description = "菜单权限DTO")
    public static class MenuPermissionDTO {
        @Schema(description = "菜单ID", example = "1")
        private Long id;
        
        @Schema(description = "菜单编码", example = "system:user")
        private String code;
        
        @Schema(description = "菜单名称", example = "用户管理")
        private String name;
        
        @Schema(description = "菜单路径", example = "/system/user")
        private String path;
        
        @Schema(description = "组件路径", example = "system/user/index")
        private String component;
        
        @Schema(description = "菜单图标", example = "user")
        private String icon;
        
        @Schema(description = "排序", example = "1")
        private Integer sortOrder;
        
        @Schema(description = "子菜单")
        private java.util.List<MenuPermissionDTO> children;
    }
}